using System;
using System.Collections.Generic;
using System.Linq;
using EPiServer.Common;
using EPiServer.Community.Blog;
using EPiServer.Community.Calendar;
using EPiServer.Community.Club;
using EPiServer.Community.Poll;
using OpenWaves.ActivityFeed.RavenDB;
using SecurityStatus = EPiServer.Community.Club.SecurityStatus;

namespace OpenWaves.ActivityFeed.EPiServer.Community
{
    public class ActivityFeedEPiServerCommunityConnector : IActivityFeedEPiServerCommunityConnector
    {
        private readonly IActivityFeedService activityFeedService;

        public ActivityFeedEPiServerCommunityConnector() : this(ServiceLocator.Resolve<IActivityFeedService>())
        {
        }

        public ActivityFeedEPiServerCommunityConnector(IActivityFeedService activityFeedService)
        {
            this.activityFeedService = activityFeedService;
        }

        public virtual void OnCalendarEventAdded(Event calendarEvent)
        {
            this.PublishUpdate(
                this.GetUpdateContent(calendarEvent), 
                calendarEvent, 
                calendarEvent.Author.Name, 
                calendarEvent.Calendar.OwnedBy.Entity as Club);
        }

        public virtual void OnPollAdded(Poll poll)
        {
        }

        public virtual void OnClubMembershipAdded(Membership membership)
        {
            this.PublishUpdate(
                this.GetUpdateContent(membership),
                membership,
                membership.User.UserName,
                membership.Club);
        }

        public virtual void OnTopicAdded(global::EPiServer.Community.Forum.Topic topic)
        {
            this.PublishUpdate(
                this.GetUpdateContent(topic),
                topic,
                topic.Author.Name,
                topic.Room.OwnedBy.Entity as Club);
        }

        public virtual void OnBlogEntryAdded(Entry entry)
        {
            this.PublishUpdate(
                this.GetUpdateContent(entry),
                entry,
                entry.Author.Name,
                entry.Blog.OwnedBy.Entity as Club);
        }

        public virtual void OnBlogEntryCommentAdded(EntryComment entryComment)
        {
            this.PublishUpdate(
                this.GetUpdateContent(entryComment),
                entryComment,
                entryComment.Author.Name,
                entryComment.Entry.Blog.OwnedBy.Entity as Club);
        }

        protected virtual UpdateContent GetUpdateContent(EntryComment entryComment)
        {
            return new BlogPostComment();
        }

        protected virtual UpdateContent GetUpdateContent(Entry entry)
        {
            return new BlogPost();
        }

        protected virtual UpdateContent GetUpdateContent(global::EPiServer.Community.Forum.Topic topic)
        {
            return new ForumTopic();
        }

        protected virtual CalendarEvent GetUpdateContent(Event calendarEvent)
        {
            return new CalendarEvent();
        }

        protected virtual UpdateContent GetUpdateContent(Membership membership)
        {
            return new ClubMembership();
        }

        protected virtual void PublishUpdate<T>(UpdateContent updateContent, T entity, string publisher, Club club) where T : FrameworkEntityBase
        {
            var topics = this.GetTopics(entity, publisher, club);

            if (club != null && club.SecurityStatus == SecurityStatus.Closed)
            {
                this.activityFeedService.PublishUpdate(updateContent, publisher, "EPiServerCommunity", topics, false, new[] { club.AsUserGroup() });
            }
            else
            {
                this.activityFeedService.PublishPublicUpdate(updateContent, publisher, "EPiServerCommunity", topics.ToArray());
            }
        }

        protected virtual IEnumerable<Topic> GetTopics(FrameworkEntityBase entity, string publisher, Club club)
        {
            var topics = new List<Topic>();
            if (club != null)
                topics.Add(club.AsTopic());

            topics.Add(Topic.FromUserId(publisher));
            topics.AddRange(entity.Tags.AsTopics());
            topics.AddRange(entity.Categories.AsTopics());

            return topics;
        }
    }
}